package com.yc.videoview;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.Component;
import ohos.event.commonevent.CommonEventSubscribeInfo;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.multimodalinput.event.TouchEvent;

public class IFloatWindowImpl extends IFloatWindow implements Component.TouchEventListener {
    private EventHandler eventHandler = new EventHandler(EventRunner.create(true));
    private FloatWindow.Builder mB;
    private FloatView mFloatView;
    private boolean isShow;
    private boolean once = true;
    private AnimatorValue mAnimator;

    private IFloatWindowImpl() {
    }

    IFloatWindowImpl(FloatWindow.Builder b) {
        mB = b;
        //这一步相当于创建系统级的window，通过windowManager添加view并且展示
        if (mB.mMoveType == MoveType.fixed) {
            mFloatView = new FloatToast(b.mApplicationContext);
        } else {
            mFloatView = new FloatPhone(b.mApplicationContext);
            initTouchEvent();
        }
        mFloatView.setSize(mB.mWidth, mB.mHeight);
        mFloatView.setGravity(mB.gravity, mB.xOffset, mB.yOffset);
        mFloatView.setView(mB.mView);
        new FloatLifecycle(mB.mApplicationContext, mB.mShow, mB.mActivities, new LifecycleListener() {
            @Override
            public void onShow() {
                show();
            }

            @Override
            public void onHide() {
                hide();
            }

            @Override
            public void onPostHide() {
                postHide();
            }
        }, new CommonEventSubscribeInfo((CommonEventSubscribeInfo) null));
    }

    @Override
    public void show() {
        if (once) {
            mFloatView.init();
            once = false;
            isShow = true;
        } else {
            if (isShow) {
                return;
            }
            getView().setVisibility(Component.VISIBLE);
            isShow = true;
        }
    }

    @Override
    public void hide() {
        if (once || !isShow) return;
        getView().setVisibility(Component.INVISIBLE);
        isShow = false;
    }

    @Override
    void dismiss() {
        mFloatView.dismiss();
        isShow = false;
    }

    @Override
    public void updateX(int x) {
        checkMoveType();
        mB.xOffset = x;
        mFloatView.updateX(x);
    }

    @Override
    public void updateY(int y) {
        checkMoveType();
        mB.yOffset = y;
        mFloatView.updateY(y);
    }

    @Override
    public void updateX(int screenType, float ratio) {
        checkMoveType();
        mB.xOffset = (int) ((screenType == WindowScreen.WIDTH ?
            WindowUtil.getScreenWidth(mB.mApplicationContext) :
            WindowUtil.getScreenHeight(mB.mApplicationContext)) * ratio);
        mFloatView.updateX(mB.xOffset);
    }

    @Override
    public void updateY(int screenType, float ratio) {
        checkMoveType();
        mB.yOffset = (int) ((screenType == WindowScreen.WIDTH ?
            WindowUtil.getScreenWidth(mB.mApplicationContext) :
            WindowUtil.getScreenHeight(mB.mApplicationContext)) * ratio);
        mFloatView.updateY(mB.yOffset);
    }

    @Override
    public int getX() {
        return mFloatView.getX();
    }

    @Override
    public int getY() {
        return mFloatView.getY();
    }

    @Override
    public Component getView() {
        return mB.mView;
    }

    void postHide() {
        if (once || !isShow) {
            return;
        }
        eventHandler.postTask(new Runnable() {
            @Override
            public void run() {
                getView().setVisibility(Component.INVISIBLE);
            }
        });

        isShow = false;
    }

    private void checkMoveType() {
        if (mB.mMoveType == MoveType.fixed) {
            throw new IllegalArgumentException("FloatWindow of this tag is not allowed to move!");
        }
    }

    private void initTouchEvent() {
        switch (mB.mMoveType) {
            case MoveType.free:
                break;
            default:
                break;
        }
    }

    /**
     * 开启动画
     */
    private void startAnimator() {
        //减速插值器
        mAnimator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        mAnimator.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
            }

            @Override
            public void onStop(Animator animator) {
            }

            @Override
            public void onCancel(Animator animator) {
            }

            @Override
            public void onEnd(Animator animator) {
                mAnimator.release();
                mAnimator = null;
            }

            @Override
            public void onPause(Animator animator) {
            }

            @Override
            public void onResume(Animator animator) {
            }
        });
        mAnimator.setDuration(mB.mDuration);
        mAnimator.start();
    }

    /**
     * 关闭动画
     */
    private void cancelAnimator() {
        if (mAnimator != null && mAnimator.isRunning()) {
            mAnimator.cancel();
        }
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        float lastX = 0, lastY = 0, changeX, changeY;
        int newX, newY;
        switch (touchEvent.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN: // 手指第一次触摸
                lastX = touchEvent.getPointerScreenPosition(0).getX();
                lastY = touchEvent.getPointerScreenPosition(0).getY();
                cancelAnimator();
                break;

            case TouchEvent.POINT_MOVE: // 手指拖动
                changeX = touchEvent.getPointerScreenPosition(0).getX() - lastX;
                changeY = touchEvent.getPointerScreenPosition(0).getY() - lastY;
                newX = (int) (mFloatView.getX() + changeX);
                newY = (int) (mFloatView.getY() + changeY);
                mFloatView.updateXY(newX, newY);
                lastX = touchEvent.getPointerScreenPosition(0).getX();
                lastY = touchEvent.getPointerScreenPosition(0).getY();
                break;
            case TouchEvent.PRIMARY_POINT_UP: //最后一根手指抬起
                switch (mB.mMoveType) {
                    case MoveType.slide:
                        int startX = mFloatView.getX();
                        int endX = (startX * 2 + component.getWidth() >
                            WindowUtil.getScreenWidth(mB.mApplicationContext)) ?
                            WindowUtil.getScreenWidth(mB.mApplicationContext) - component.getWidth() : 0;
                        mAnimator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                            @Override
                            public void onUpdate(AnimatorValue animatorValue, float v) {
                                int x = (int) animatorValue.getDuration();
                                mFloatView.updateX(x);
                            }
                        });
                        startAnimator();
                        break;
                    case MoveType.back:
                        startAnimator();
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
        return false;
    }
}
